package game.zqll.mod;

import com.badlogic.gdx.Gdx;
import com.typesafe.config.Config;
import com.typesafe.config.ConfigFactory;
import game.zqll.GameMod;

import java.io.File;
import java.io.FileFilter;
import java.io.FileReader;
import java.util.*;

public class ModLoader {

    // 获取项目根路径
    private final static String projectRootPath = System.getProperty("user.dir");
    // 拼接 mods 文件夹路径
    private final static String modsFolderPath = projectRootPath + File.separator + "mods";
    // 创建 File 对象表示 mods 文件夹
    public final static File modsFolder = new File(modsFolderPath);
    public final static File modsConfigFile = new File(modsFolderPath + File.separator + "ModsConfig.conf");

    // 新增静态变量用于缓存
    private static Map<String, ModContainer> cachedModMap = new HashMap<>();
    // modId -> absolutePath
    private static Map<String, File> modId2PathMap = new HashMap<>();
    // modId -> ModContainer
    private static Map<String, ModContainer> cachedLoadModMap = new HashMap<>();
    private static String lastFileFingerprint = "";

    static {
        // 定义 jar 文件过滤器
        FileFilter jarFilter = file -> file.isFile() && file.getName().endsWith(".jar");
        // 获取 mods 文件夹中所有 jar 文件
        File[] jarFiles = modsFolder.listFiles(jarFilter);

        // 用 Map 按 modId 索引所有 mod
        final Map<String, ModContainer> modIdMap = new LinkedHashMap<>();
        if (jarFiles != null) {
            for (File jarFile : jarFiles) {
                System.out.println("加载mod文件，路径: " + jarFile.getAbsolutePath());
                try {
                    ModMeta modMeta = ModMeta.readFromJar(jarFile.getAbsolutePath());
                    modId2PathMap.put(modMeta.modId, jarFile);
                } catch (Exception e) {
                    throw new RuntimeException(e);
                }
            }
        } else {
            System.out.println("未找到 mods 文件夹或者 mods 文件夹中没有 jar 文件");
        }
    }

    public static Map<String, ModContainer> scanMods() {
        // 生成当前文件指纹（文件名+最后修改时间）
        String currentFingerprint = generateFileFingerprint();

        // 检查是否需要重新扫描（时间戳过期或文件指纹变化）
        if (currentFingerprint.equals(lastFileFingerprint)) {
            return cachedModMap;
        }


        // 定义 jar 文件过滤器
        FileFilter jarFilter = file -> file.isFile() && file.getName().endsWith(".jar");
        // 获取 mods 文件夹中所有 jar 文件
        File[] jarFiles = modsFolder.listFiles(jarFilter);

        // 用 Map 按 modId 索引所有 mod
        final Map<String, ModContainer> modIdMap = new LinkedHashMap<>();
        if (jarFiles != null) {
            for (File jarFile : jarFiles) {
                System.out.println("加载mod文件，路径: " + jarFile.getAbsolutePath());
                ModContainer container = ModLoader.loadMod(jarFile);
                if (container != null && container.meta != null && container.meta.modId != null) {
                    modIdMap.put(container.meta.modId, container);
                }
            }
        } else {
            System.out.println("未找到 mods 文件夹或者 mods 文件夹中没有 jar 文件");
        }

        cachedModMap.clear();
        cachedModMap.putAll(modIdMap);
        // 更新缓存和状态标记
        lastFileFingerprint = currentFingerprint;

        return cachedModMap;
    }

    // 生成文件指纹（基于文件名和最后修改时间）
    private static String generateFileFingerprint() {
        File[] files = modsFolder.listFiles(file -> file.isFile() && file.getName().endsWith(".jar"));
        if (files == null) return "";

        StringBuilder sb = new StringBuilder();
        for (File f : files) {
            sb.append(f.getName())
                .append("-")
                .append(f.lastModified())
                .append("|");
        }
        return sb.toString();
    }

    public static List<String> readActiveMods() {
        List<String> result = new ArrayList<>();
        if (!modsConfigFile.exists()) return result;
        try (FileReader reader = new FileReader(modsConfigFile)) {
            Config config = ConfigFactory.parseReader(reader);
            if (config.hasPath("activeMods")) {
                result = config.getStringList("activeMods");
            }
        } catch (Exception e) {
            System.err.println("[ModsConfigReader] 读取 ModsConfig.conf 失败: " + e.getMessage());
        }
        return result;
    }

    public static ModContainer loadMod(File jarFile) {
        if (jarFile == null) {
            return null;
        }
        return cachedLoadModMap.computeIfAbsent(jarFile.getPath(), s -> {
            ClassLoader originalLoader = Thread.currentThread().getContextClassLoader();
            try {
                // ModLoader 里加载 mod 时
                ModMeta modMeta = ModMeta.readFromJar(jarFile.getPath());
                List<ClassLoader> dependencyClassLoaders = new ArrayList<>();
                for (ModMeta.Dependency dependency : modMeta.dependencies) {
                    ModContainer modContainer = loadMod(modId2PathMap.get(dependency.modId));
                    if (modContainer != null) {
                        dependencyClassLoaders.add(modContainer.classLoader);
                    }
                }
                ModClassLoader modClassLoader = new ModClassLoader(jarFile.toURI().toURL(), dependencyClassLoaders);

                Thread.currentThread().setContextClassLoader(modClassLoader);

                Class<?> modMainClass = Class.forName(modClassLoader.getMainClass(), true, modClassLoader);
                Object mainClassInstance = modMainClass.getDeclaredConstructor().newInstance();

                if (mainClassInstance instanceof GameMod mod) {
                    return new ModContainer(modClassLoader.modMeta, jarFile, mod, modClassLoader);
                }
            } catch (Exception e) {
                Gdx.app.error("ModLoader", "加载失败: " + jarFile, e);
            } finally {
                Thread.currentThread().setContextClassLoader(originalLoader);
            }
            return null;
        });

    }

}
